package com.loren.demo14.config;

import com.loren.demo14.filter.TokenAuthenticationFilter;
import com.loren.demo14.handler.CustomAccessDeniedHandler;
import com.loren.demo14.handler.LoginFailureHandler;
import com.loren.demo14.handler.LoginSuccessHandler;
import com.loren.demo14.handler.TokenAuthenticationEntryPoint;
import lombok.AllArgsConstructor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;

@Configuration
@EnableWebSecurity
@AllArgsConstructor
@EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true)
public class AuthSecurity extends WebSecurityConfigurerAdapter {

    /**
     * 登录成功的处理器
     */
    private final LoginSuccessHandler loginSuccessHandler;

    /**
     * 登录失败的处理器
     */
    private final LoginFailureHandler loginFailureHandler;

    /**
     * 未授权访问时的处理类
     */
    private final TokenAuthenticationEntryPoint tokenAuthenticationEntryPoint;

    /**
     * 访问拒绝的处理类 - 没有权限访问时
     */
    private final CustomAccessDeniedHandler customAccessDeniedHandler;

    /**
     * token认证的过滤器
     */
    private final TokenAuthenticationFilter tokenAuthenticationFilter;

    /**
     * 加密方式
     */
    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        // 配置登录成功处理器和登录失败处理器
        http.formLogin().successHandler(loginSuccessHandler).failureHandler(loginFailureHandler)
                .and()
                // 所有的请求都需要认证
                .authorizeRequests().anyRequest().authenticated()
                .and()
                // 禁用session的配置
                .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
                .and()
                // 未授权访问时的处理
                .exceptionHandling().authenticationEntryPoint(tokenAuthenticationEntryPoint).accessDeniedHandler(customAccessDeniedHandler)
                .and()
                // 配置token认证的过滤器
                .addFilterBefore(tokenAuthenticationFilter, UsernamePasswordAuthenticationFilter.class)
                // 禁用csrf
                .csrf().disable();
    }
}